﻿#include "WinFormBasic_GUI.h"
#pragma comment(lib, "Msimg32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "GDI32.lib")
#pragma comment(lib, "comctl32.lib")               // 引入 richedit
HMODULE hRichEdit = LoadLibraryW(L"Msftedit.dll"); // 引入 richedit
using namespace std;
static std::vector<wchar_t> static_wideString;
LPCWSTR ConvertToLPCWSTR(const char* str) {
    // 计算所需的宽字符长度
    int wideCharLen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
    if (wideCharLen <= 0) {
        return nullptr; // 转换失败
    }

    // 调整 static_wideString 的大小
    static_wideString.resize(wideCharLen);

    // 执行转换
    MultiByteToWideChar(CP_UTF8, 0, str, -1, &static_wideString[0], wideCharLen);

    // 返回宽字符字符串
    return &static_wideString[0];
}
void Auto_load_ICO(HWND hwndWindows) // 动态加载图标并设置为窗口图标
{
    HICON hIcon = (HICON)LoadImageW(
        NULL,
        L"Heart.ico",
        IMAGE_ICON,
        0, 0,
        LR_LOADFROMFILE | LR_DEFAULTSIZE);
    if (hIcon)
    {
        SendMessageW(hwndWindows, WM_SETICON, ICON_BIG, (LPARAM)hIcon);   // 设置大图标
        SendMessageW(hwndWindows, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); // 设置小图标
    }
}

int RunMessageLoop() // 消息循环
{
    MSG msg = {0};
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    FreeLibrary(hRichEdit);
    return (int)msg.wParam;

}

BOOL InitializeWindowClass(HINSTANCE hInstance,LPCWSTR windowClass) // 初始化窗口类

{
    LPCWSTR windowClassB = windowClass.c_str();
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszClassName = windowClassB; 
    return RegisterClass(&wc);
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CTLCOLORSTATIC: // 设置静态控件（如标签）的背景颜色
    {
        HDC hdcStatic = (HDC)wParam;
        SetBkColor(hdcStatic, RGB(255, 255, 255));  // 设置背景颜色为白色
        return (LRESULT)GetStockObject(NULL_BRUSH); // 返回透明刷子
    }
    break;
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);                        // 只重绘受影响的区域
        FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1)); //  填充背景色
        EndPaint(hwnd, &ps);                                    //  结束绘制
    }
    break;
    case WM_COMMAND:
        Button_Event(hwnd, wParam, lParam); // 处理按钮事件
        break;
    case WM_DROPFILES: // 处理拖放文件消息
        Drop_To_Display_Path(hwnd, wParam);
        break;
    case WM_DESTROY:
        PostQuitMessage(0); // 退出应用程序
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

void Drop_To_Display_Path(HWND hwnd, WPARAM wParam)
{
    HDROP hDrop = (HDROP)wParam;
    wchar_t filePath[MAX_PATH];
    DragQueryFileW(hDrop, 0, filePath, MAX_PATH); // 获取第一个文件的路径
    POINT pt;
    DragQueryPoint(hDrop, &pt);                       // 获取鼠标拖放的位置
    HWND hwndTarget = ChildWindowFromPoint(hwnd, pt); // 获取目标控件
    SetWindowTextW(hwndTarget, filePath);             // 将文件路径显示在文本框
    DragFinish(hDrop);                                // 释放拖放资源
}

std::wstring string_to_wstring(const std::string &str) // 字符串转换 string_to_wstring
{
    std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
    return converter.from_bytes(str);
}

std::string wstring_to_string(const wchar_t *wstr) //  字符串转换 wstring_to_string
{
    std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
    return converter.to_bytes(wstr);
}

class Control // 基础控件类
{
protected:
    HWND hwnd;            // 控件的窗口句柄
    std::wstring caption; // 控件的标题或文本
    RECT rect;            // 控件的位置和大小
public:
    Control(HWND parent, const std::wstring &clsName, const std::wstring &caption, int x, int y, int width, int height)
    {
        rect.left = x;
        rect.top = y;
        rect.right = x + width;
        rect.bottom = y + height;

        hwnd = CreateWindowExW(
            0,                     // 扩展样式
            clsName.c_str(),       // 类名
            caption.c_str(),       // 标题
            WS_CHILD | WS_VISIBLE, // 样式
            x, y, width, height,   // 位置和大小
            parent,                // 父窗口句柄
            NULL,                  // 不使用菜单
            GetModuleHandle(NULL), // 当前实例
            NULL                   // 不使用额外数据
        );
    }

    Control(HWND hwndParent, int x, int y, int width, int height, HINSTANCE hInstance, HMENU ID) // 仅供 RichTextBox 使用，创建 RICHEDIT50W 富文本控件
    {
        rect.left = x;
        rect.top = y;
        rect.right = x + width;
        rect.bottom = y + height;
        HWND hwnd;
        hwnd = CreateWindowExW(
            0,
            L"RICHEDIT50W",
            L"",
            WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
            x, y, width, height,
            hwndParent,
            (HMENU)ID,
            hInstance,
            NULL);
    }

    virtual ~Control() // 析构函数
    {
        if (hwnd)
        {
            DestroyWindow(hwnd); // 销毁窗口
        }
    }
    void SetCaption(const std::wstring &newCaption) // 设置控件的标题或文本
    {
        caption = newCaption;
        SetWindowTextW(hwnd, caption.c_str()); // 设置控件的标题或文本
    }

    std::wstring GetCaption() const // 获取控件的标题或文本
    {
        return caption;
    }

    HWND GetHandle() const // 获取控件的窗口句柄
    {
        return hwnd;
    }
};

HWND CreateWindows(HINSTANCE hInstance, const wchar_t *windowClass, const wchar_t *windowTitle, int width, int height)
{
    return CreateWindowExW(
        0,
        windowClass,
        windowTitle,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        width, height,
        NULL,
        NULL,
        hInstance,
        NULL);
}

class RichTextBox : public Control // 富文本框控件类
{
    /*
    1.设置大小及位置
    2.获取大小及位置
    3.设置内容
    4.获取内容
    5.是否输入状态
    6.设置内容长度
    7.获取内容长度
    8.查找内容
    7.替换内容
    */
public:
    RichTextBox(HWND hwndParent, int x, int y, int width, int height, HINSTANCE hInstance, HMENU ID) : Control(hwndParent, x, y, width, height, hInstance, ID) {};
};
class CommandButton : public Control // 按钮控件类
{
    /*
    1.设置大小及位置
    2.获取大小及位置
    3.设置文本
    4.获取文本
    5.获取按钮ID
    6.设置按钮ID
    7.设置按钮状态
    8.获取按钮状态
    9.设置按钮图标
    10.获取按钮图标
    11.按钮单击事件
    */
public:
    int ButtonID;
    CommandButton(HWND parent, const std::wstring &caption, int x, int y, int width, int height, int ID) : Control(parent, L"BUTTON", caption, x, y, width, height) // 调用基类的构造函数
    {
        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | BS_PUSHBUTTON);
        ButtonID = (int)(uintptr_t)ID;
        SetWindowLong(hwnd, GWL_ID, ButtonID);
    }
};

class Label : public Control //  标签控件类
{
    /*
    1.设置大小及位置
    2.获取大小及位置
    3.设置文本
    4.获取文本
    */
public:
    Label(HWND parent, const std::wstring &caption, int x, int y, int width, int height, int ID)
        : Control(parent, L"STATIC", caption, x, y, width, height)
    {
        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | SS_SIMPLE);
    }
};

class CheckBox : public Control // 复选框控件类
{
    /*
    1.设置大小及位置
    2.获取大小及位置
    3.设置选中状态
    4.设置非选中状态
    5.获取状态
    */
public:
    CheckBox(HWND parent, const std::wstring &caption, int x, int y, int width, int height, int ID)
        : Control(parent, L"BUTTON", caption, x, y, width, height)
    {
        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | BS_AUTOCHECKBOX);
    }
};
class OptionButton : public Control // 单选按钮控件类
{
    /*
    1.设置大小及位置
    2.获取大小及位置
    3.获取状态
    */
public:
    OptionButton(HWND parent, const std::wstring &caption, int x, int y, int width, int height, int ID)
        : Control(parent, L"BUTTON", caption, x, y, width, height)
    {
        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | BS_AUTORADIOBUTTON);
    }
};
class Frame : public Control // 框架控件类
{
    /*
    1.设置大小及位置
    2.获取大小及位置
    3.设置文本
    4.获取文本
    */
public:
    Frame(HWND parent, const std::wstring &caption, int x, int y, int width, int height, int ID)
        : Control(parent, L"BUTTON", caption, x, y, width, height)
    {
        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | BS_GROUPBOX);
    }
};

class Timer // 定时器控件类
{
    /*
1.设置大小及位置
2.获取大小及位置
*/
private:
    HWND hwnd;
    UINT timerID;

public:
    Timer(HWND parent, UINT id, UINT interval) : hwnd(parent), timerID(id)
    {
        SetTimer(hwnd, timerID, interval, NULL);
    }

    ~Timer()
    {
        KillTimer(hwnd, timerID);
    }
};